<template>
  <div class="web-container">
    <div class="message-list" ref="scrollContainer">
      <!-- 错误提示 -->
      <!-- <div v-if="error" class="error">{{ error }}</div> -->
      <!-- 流式内容渲染 -->
      <div class="messge" v-for="(data,dIndex) in pageData" :key="dIndex">
        <div class="answer-problem" v-if="data.type=='user'">
          <p>{{data.problem}}</p>
        </div>
        <!-- v-for="(item,index) in answer" :key="index" -->
        <div class="answer-container" v-else>
          <div class="answer-ai">
            <img src="~@/assets/images/deepseek.png" />
            <div class="answer-aiInfo" v-if="seekLoading && dIndex == Number(Number(pageData.length) - 1 )">
              <div class="loader"></div>深度思考中
            </div>
            <div class="answer-aiInfo" v-else>已深度思考</div>
          </div>
          <div v-if="data.thinkList.length>0" class="thinkBox">{{data.thinkList}}</div>
          <div v-if="data.answer.length>0" class="answerBox">{{data.answer}}</div>
        </div>
      </div>


    </div>
    <div class="inputInfo">
      <el-input class="inputBox" v-model="inputText" @keyup.enter.native="fetchStream()"
        placeholder="输入与DeepSeek的对话"></el-input>
      <el-button type="primary" icon="el-icon-s-promotion" :disabled='seekLoading' @click="fetchStream"
        class="submit"></el-button>
    </div>
  </div>
</template>

<script>
  import {
    getDeepseekResponse
  } from '@/api/deepseek';
  const controller = new AbortController();
  export default {
    data() {
      return {
        inputText: '', //问题
        answer: '', // 问答列表
        buffer: "", // 原始数据缓冲区
        thinkList: '',
        seekLoading: false, //思考中
        error: null,
        eventSource: null,
        pageIndex: -1, //当前数组项
        problemList: [],
        errorNum: 0, //服务器连接失败次数 五次以上中止
        pageData: [], //页面数组
      };
    },
    // beforeDestroy() {
    //   if (this.eventSource) this.eventSource.close();
    //   controller.abort();
    // },
    created() {

    },
    methods: {
      async fetchStream() {
        if (this.seekLoading) {
          return
        }
        if (!this.inputText) {
          this.$message({
            message: '请输入您的问题~',
            type: 'warning'
          });
          return
        } else {
          var obj = {
            type: 'user',
            problem: this.inputText
          }
          this.pageData.push(obj)
        }

        this.seekLoading = true;
        this.error = null;
        this.buffer = "";
        var data = {
          answer: '',
          thinkList: '',
          type: 'ai',
        }
        this.pageData.push(data)
        this.$nextTick(() => {
          const container = this.$refs.scrollContainer;
          container.scrollTop = container.scrollHeight;
        });
        try {
          //使用 Fetch API（需要自定义 headers）
          await this.initFetchStream();
        } catch (err) {
          this.handleError(err);
        }
      },
      // Fetch API + 流式处理（推荐，支持自定义 headers）
      async initFetchStream() {
        var contentInfo = this.inputText;
        this.inputText = '';
        var requestData = {
          model: "deepseek-reasoner", // 推理模型
          messages: [{
            role: "user",
            content: contentInfo
          }],
          stream: true, //如果设置为 True，将会以 SSE（server-sent events）的形式以流式发送消息增量。消息流以 data: [DONE] 结尾。
        }
        const response = await fetch(process.env.VUE_APP_API_SERVICE, {
          headers: {
            Authorization: `Bearer sk-80aed5abc9f746a6bb6b4cdf7f61fdef`,
            "Content-Type": "application/json",
          },
          method: 'POST',
          body: JSON.stringify(requestData),
          signal: controller.signal
        });
        const reader = response.body.getReader();
        const decoder = new TextDecoder();

        // 持续读取流数据
        while (true) {
          const {
            done,
            value
          } = await reader.read();
          if (done) {
            this.seekLoading = false;
            break;
          }
          this.buffer += decoder.decode(value, {
            stream: true
          });
          this.processBuffer();
        }
      },

      // 处理缓冲区数据（核心解析逻辑）
      processBuffer() {
        // 获取数组位置
        const index = Number(this.pageData.length) - 1;
        // 假设数据块以 "\n\n" 分割
        const chunks = this.buffer.split("\n\n");
        // 保留未处理完的数据
        this.buffer = chunks.pop() || "";
        chunks.forEach(chunk => {
          const cleanChunk = chunk.trim().replace(/^data: /, "");
          if (!cleanChunk || cleanChunk === "[DONE]") return;

          try {
            const parsed = JSON.parse(cleanChunk);
            // 逐步更新ai思考
            if (parsed.choices[0].delta.reasoning_content) {
              this.pageData[index].thinkList += parsed.choices[0].delta.reasoning_content;
              this.$forceUpdate()
            }
            // 逐步更新答案
            if (parsed.choices[0].delta.content) {
              this.pageData[index].answer += parsed.choices[0].delta.content;
              this.$forceUpdate()
            }
            // 滚动到底部
            this.$nextTick(() => {
              const container = this.$refs.scrollContainer;
              container.scrollTop = container.scrollHeight;
            });
          } catch (err) {
            this.errorNum++;

            if (this.errorNum >= 5) {
              this.seekLoading = false
              this.pageData[index].thinkList = '服务器繁忙，请稍后再试';
              // controller.abort();
            }

          }
        });
      },

      handleError(err) {
        this.error = err.message || "流式请求失败";
        this.seekLoading = false;
        if (this.eventSource) this.eventSource.close();
      },


    }
  };
</script>
<style lang='scss' scoped>
  .char {
    opacity: 0;
    animation: fadeIn 0.3s forwards;
  }

  .answer-container {
    padding: 5px;
    font-size: 14px;
  }

  .answer-problem {
    font-size: 15px;
    color: #262626;
    display: flex;
    width: 100%;
    justify-content: flex-end;
  }

  .answer-problem p {
    background-color: #eff6ff;
    padding: 10px 15px;
    border-radius: 14px;
    white-space: pre-wrap;
    word-break: break-word;
    max-width: calc(100% - 100px);
  }

  .answer-ai {
    display: flex;
    align-items: center;
    margin-bottom: 10px;

    img {
      height: 32px;
      width: 32px;
    }
  }

  .answer-aiInfo {
    height: 32px;
    width: 110px;
    font-size: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #eee;
    border-radius: 10px;
    color: #666;
    margin-left: 10px;
  }

  .thinkBox {
    border-left: 2px solid #e5e5e5;
    font-size: 13px;
    color: #8b8b8b;
    white-space: pre-wrap;
    margin: 0;
    padding: 0 0 0 13px;
    max-width: 80%;
  }

  .answerBox {
    margin-top: 10px;
    font-size: 15px;
    color: #000;
    white-space: pre-wrap;
    line-height: 20px;
    max-width: 80%;
  }

  @keyframes fadeIn {
    to {
      opacity: 1;
    }
  }

  .loading:after {
    content: '...';
    animation: dots 1s infinite;
  }

  @keyframes dots {

    0%,
    20% {
      content: '.';
    }

    40% {
      content: '..';
    }

    60% {
      content: '...';
    }

    80%,
    100% {
      content: '';
    }
  }

  .web-container {
    margin: 15px;
    border-radius: 10px;
    height: calc(100vh - 116px);
    padding: 15px;
    background: #fff;
  }

  .inputInfo {
    height: 60px;
    width: calc(100% - 20px);
    margin: 0 auto;
    background-color: rgb(243, 244, 246);
    box-shadow: 0px 0px 0px .5px #f3f4f6;
    border-radius: 24px;
    padding: 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  ::v-deep .el-input__inner {
    background-color: rgb(243, 244, 246) !important;
    border: none !important;
  }

  .submit {
    background: #2a61ff;
    color: #fff;
    cursor: pointer;
    border-radius: 50%;
    height: 40px;
    width: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .message-list {
    padding: 0 10px 40px 10px;
    overflow-y: auto;
    height: calc(100% - 60px);

  }


  .loader {
    display: inline-block;
    width: 15px;
    height: 15px;
    border: 2px solid #f3f3f3;
    border-radius: 50%;
    border-top-color: #2a61ff;
    margin-right: 5px;
    animation: spin 1s linear infinite;
  }

  /* 动画 */
  @keyframes messageAppear {
    from {
      opacity: 0;
      transform: translateY(20px);
    }

    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }

    100% {
      transform: rotate(360deg);
    }
  }
</style>
